#include <fstream>
#include "json/json.h"

#include "Data/Exceptions.h"
#include "Data/Serialization.h"
#include "Data/LoadingAndSaving.h"

namespace data {

	std::string GetFileContents( const std::string& filename ) {
		std::string text;
		std::ifstream file( filename.c_str() );

		if( !file.is_open() )
			throw ResourceOpenException( filename );

		std::getline( file, text, '\0' );

		file.close();
		return text;
	}

	void SetFileContents( const std::string& filename, const std::string& contents ) {
		std::ofstream file( filename.c_str() );
		if( !file.is_open() )
			throw ResourceOpenException( filename );

		file << contents;
		file.close();
	}

	Json::Value Load( const std::string& filename ) {
		std::string document = GetFileContents( filename );
		Json::Reader reader;
		Json::Value root;
		bool parsingSuccessful = reader.parse( document, root );
		if( !parsingSuccessful )
			throw ParserException( filename, reader.getFormattedErrorMessages() );
		return root;
	}

	void Save( const std::string& filename, const Json::Value& json ) {
		Json::StyledWriter writer;
		std::string document = writer.write( json );
		SetFileContents( filename, document );
	}

	Scene LoadScene( const std::string& filename ) {
		Json::Value jScene = Load( filename );
		return DeserializeScene( jScene );
	}

	void SaveScene( const Scene& scene, const std::string& filename ) {
		Json::Value jScene = SerializeScene( scene );
		Save( filename, jScene );
	}

	Map LoadMap( const std::string& filename ) {
		Json::Value jMap = Load( filename );
		return DeserializeMap( jMap );
	}

	void SaveMap( const Map& map, const std::string& filename ) {
		Json::Value jMap = SerializeMap( map );
		Save( filename, jMap );
	}

	CreatureDef LoadCreatureDef( const std::string& filename ) {
		Json::Value jCreatureDef = Load( filename );
		return DeserializeCreatureDef( jCreatureDef );
	}

	void SaveCreatureDef( const CreatureDef& creatureDef, const std::string& filename ) {
		Json::Value jCreatureDef = SerializeCreatureDef( creatureDef );
		Save( filename, jCreatureDef );
	}

	RotorDef LoadRotorDef( const std::string& filename ) {
		Json::Value jRotorDef = Load( filename );
		return DeserializeRotorDef( jRotorDef );
	}

	void SaveRotorDef( const RotorDef& rotorDef, const std::string& filename ) {
		Json::Value jRotorDef = SerializeRotorDef( rotorDef );
		Save( filename, jRotorDef );
	}

	Model LoadModel( const std::string& filename ) {
		Json::Value jModel = Load( filename );
		return DeserializeModel( jModel );
	}

	void SaveModel( const Model& model, const std::string& filename ) {
		Json::Value jModel = SerializeModel( model );
		Save( filename, jModel );
	}

	Body LoadBody( const std::string& filename ) {
		Json::Value jBodyDef = Load( filename );
		return DeserializeBody( jBodyDef );
	}

	void SaveBody( const Body& body, const std::string& filename ) {
		Json::Value jBodyDef = SerializeBody( body );
		Save( filename, jBodyDef );
	}
}
